<?php

namespace App\exption\push\Hpush;

use App\interf\Push;
use Illuminate\Support\Facades\Redis;

/*华为推送*/
class Hpush implements Push
{

    const GETACCESSTOKENURL = 'https://login.vmall.com/oauth2/token';
    const PUSHMESSAGEURL = 'https://api.push.hicloud.com/pushsend.do';

    protected $accessToken=null;
    protected $app_id;
    protected $app_secret;
    protected $appPkgName='com.xianghe.ivy';

    public function __construct()
    {
        /*$this->app_id = config('push')['hpush']['app_id'];
        $this->app_secret = config('push')['hpush']['app_secret'];*/
        // 获取临时令牌
        //$data = $this->getAccessToken();
    }

    /*
     * 单个推送
     * */
    public function singlePush($params)
    {
        if( !is_array($params) || !array_key_exists('title', $params) || !array_key_exists('content', $params) || !array_key_exists('mobile_list', $params) )
            return ['status'=>'error', 'message'=>'参数异常', 'message_code'=>'10128','data'=>$params];

        $content_params['title'] = $params['title'];
        $content_params['content'] = $params['content'];
        $content_params['bi_tag'] = $params['bi_tag'] ?? '';
        $content_params['icon'] = $params['icon'] ?? '';
        $content_params['extend'] = $params['extend'] ?? '';
        $mobile_list = $params['mobile_list'];
        $notify_id = $params['notify_id'];

        // 消息类型：1 透传异步消息 3 系统通知栏异步消息 注意：2和4以后为保留后续扩展使用
        $msg_type = $params['msg_type'] ?? 3;
        // 通知栏消息body内容
        $action_type = $params['action_type'] ?? 3;
        return $this->SendPushMessage($content_params, $mobile_list, $msg_type, $action_type, $notify_id);
    }

    /*
     * 批量推送
     * param array $params = [
     * 'titel'=>必填
     * 'content'=>必填
     * 'mobile_list'=>必填
     * 'bi_tag'=>'n'
     * 'icon'=>'n']  // 消息内容参数
     * param array $mobile_list       移动设备号列表   最多1000
     * */
    public function batchPush($params)
    {
        if( !is_array($params) || !array_key_exists('title', $params) || !array_key_exists('content', $params) || !array_key_exists('mobile_list', $params) || !is_array($params['mobile_list']))
            return ['status'=>'error', 'message_code'=>10128, 'message'=>'参数异常', 'data'=>$params];
        if(count($params['mobile_list']) > 1000)
            return ['status'=>'error', 'message_code'=>10129, 'message'=>'每次发送最多1000', 'data'=>$params];

        $content_params['title'] = $params['title'];
        $content_params['content'] = $params['content'];
        $content_params['bi_tag'] = $params['bi_tag'] ?? '';
        $content_params['icon'] = $params['icon'] ?? '';
        $mobile_list = $params['mobile_list'];

        // 消息类型：1 透传异步消息 3 系统通知栏异步消息 注意：2和4以后为保留后续扩展使用
        $msg_type = $params['meg_type'] ?? 3;
        // 通知栏消息body内容
        $action_type = $params['action_type'] ?? 3;

        return $this->SendPushMessage($content_params, $mobile_list, $msg_type, $action_type);
    }

    /*
     * 消息推送
     * @param array $content_params = ['titel'=>'y' , 'content'=>'y', 'bi_tag'=>'n', 'icon'=>'n']  // 消息内容参数
     * @param array $mobile_list       移动设备号列表   最多1000
     * @param int $msg_type             消息类型：1 透传异步消息 3 系统通知栏异步消息 注意：2和4以后为保留后续扩展使用
     * @return int $action_type         消息点击动作参数 :1 自定义行为：行为由参数intent定义  2 打开URL：URL地址由参数url定义  3 打开APP：默认值，打开App的首页
     * */
    protected function SendPushMessage($content_params=[], $mobile_list=[], $msg_type=3, $action_type = 3, $notify_id)
    {
        $token = self::getAccessToken();

        $urlParams = array();
        $nsp_ctx = array();
        $params = array();

        $ext = [];
        // 扩展信息，含BI消息统计，特定展示风格，消息折叠。
        if(isset($content_params['bi_tag']) && !empty($content_params['bi_tag']))
            $ext['biTag'] = $content_params['bi_tag']; // 设置消息标签，如果带了这个标签，会在回执中推送给CP用于检测某种类型消息的到达率和状态
        if(isset($content_params['icon']) && !empty($content_params['icon']))
            $ext['icon'] = $content_params['icon'];; // 自定义推送消息在通知栏的图标,value为一个公网可以访问的URL

        unset($params);

        $body['title'] = $content_params['title']; // 消息标题
        $body['content'] = $content_params['content']; // 消息内容体
        // app 业务内容
        $body['type'] = (int)$notify_id;
        if(isset($content_params['extend']) && !empty($content_params['extend']))
            foreach ($content_params['extend'] as $key=>$value)
                $body[$key] = $value;

        $param['appPkgName'] = 'com.xianghe.ivy';//$this->appPkgName; // 定义需要打开的appPkgName
        $action['type'] = $action_type; // 类型3为打开APP，其他行为请参考接口文档设置
        $action['param'] = $param; // 消息点击动作参数

        $msg['type'] = (int)$msg_type; // 3: 通知栏消息，异步透传消息请根据接口文档设置
        $msg['action'] = $action; // 消息点击动作
        $msg['body'] = $body; // 通知栏消息body内容
        $hps['msg'] = $msg;
        $hps['ext'] = $ext;
        $payload['hps'] = $hps;
        $nsp_ctx['ver'] = '1';

        $nsp_ctx['appId'] = '100434711';//config('push')['hpush']['app_id'];
        $params['nsp_ctx'] = json_encode($nsp_ctx);
        $params['access_token'] = $token;
        $params['payload'] = json_encode($payload);
        $params['device_token_list'] = json_encode([$mobile_list]);
        $params['nsp_svc'] = 'openpush.message.api.send';
        $params['nsp_ts'] = time();

        $data = $this->request(self::PUSHMESSAGEURL, $params, ['Content-Type: application/x-www-form-urlencoded; charset=utf-8'], true);
        
        $json_decode_data = json_decode($data, true);
        // 推送成功
        if(isset($json_decode_data['code']) && $json_decode_data['code'] == '80000000' && strtoupper($json_decode_data['msg']) == 'SUCCESS')
            return ['status'=>'success', 'message_code'=>10130, 'message'=>'推送成功', 'errorCode'=>'0', 'push_response'=>$json_decode_data];

        return ['status'=>'error', 'message_code'=>10131, 'message'=>$json_decode_data['msg'] ?? '推送消息异常', 'errorCode'=>$json_decode_data['code'] ?? '未知状态码', 'push_response'=>$json_decode_data];
    }

    /*
     * 获取临时令牌 access token  有效期7天
     * */
    public static function getAccessToken()
    {
        // 获取临时令牌
        if(empty(Redis::get('push_access_token_h'))){
            $params = [];
            $params['grant_type'] = 'client_credentials';
            $params['client_id'] = '100434711';
            $params['client_secret'] = 'f076da71e73b39be8c522019081c9574';

            $res = self::request(
                self::GETACCESSTOKENURL,
                ['grant_type' => 'client_credentials', 'client_secret' => $params['client_secret'], 'client_id' => $params['client_id'] ],
                ['Content-Type: application/x-www-form-urlencoded; charset=utf-8'],
                true);

            $data = json_decode($res, true);
            if(!isset($data['access_token']))
                return ['status'=>'error', 'message'=>'获取token 失败', 'message_code'=>10132];
            Redis::setex('push_access_token_h', $data['expires_in'], $data['access_token']);
            return $data['access_token'];
        }

        return Redis::get('push_access_token_h');
        // 获取缓存
        // $this->accessToken = Redis::get('push_access_token_h');
    }

    public static function request($url, $postData = [], $header = [], $formUrlencoded = false)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if ($header) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }


        if ($postData) {

            curl_setopt($ch, CURLOPT_POST, true);
            //如果不用http_build_query你就会踩到坑的，你可以试试
            if($formUrlencoded){
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
            }else{
                curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            }
        }

        $response  = curl_exec($ch);
        if ($errno = curl_errno($ch)) {
            $error = curl_error($ch);
            $this->errmsg = $error;
            $this->errno = $errno;
            curl_close($ch);

            return false;
        }
        curl_close($ch);

        return $response ;
    }
}

